package com.corticon.dialogs.dao.hibernate;

import static org.hibernate.criterion.Restrictions.*;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;

import org.hibernate.Criteria;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.MatchMode;

import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;

import com.corticon.dialogs.dao.LookupDAO;
import com.corticon.dialogs.model.LookupBase;
import com.corticon.dialogs.util.Pager;
import org.hibernate.criterion.CriteriaSpecification;

@Repository("lookupDAO")
public class LookupHibernateDAO extends GenericHibernateDAO<LookupBase, String> implements LookupDAO {

    @Override
    public List<LookupBase> search(Class<LookupBase> lookupClass, String keywords,
        List<String> groupNames,
        Pager pager) {

        List<LookupBase> results = new ArrayList<LookupBase>();
        results = getPageOfData(buildSearchCriteria(lookupClass, keywords, groupNames), pager);
        return results;
    }

    @Override
    public long getCountForSearch(Class<LookupBase> lookupClass, String keywords,
        List<String> groupNames) {
        return getCount(buildSearchCriteria(lookupClass, keywords, groupNames));
    }

    private Criteria buildSearchCriteria(Class<LookupBase> lookupClass, String keywords,
        List<String> groupNames) {
        // The lookupClass cannot be null.
        Assert.notNull(lookupClass);

        Criteria searchCriteria = getSession().createCriteria(lookupClass);

        if (StringUtils.isNotEmpty(keywords)) {
            keywords = keywords.trim();
            searchCriteria.add(disjunction().add(ilike("code", keywords, MatchMode.ANYWHERE)).add(
                ilike("name", keywords, MatchMode.ANYWHERE)).add(ilike("description", keywords,
                MatchMode.ANYWHERE)));
        }

        searchCriteria.createCriteria("userGroup", CriteriaSpecification.LEFT_JOIN);
        Disjunction groupCriterion = disjunction();
        for (String groupName : groupNames) {
            groupCriterion.add(eq("userGroup.name", groupName));
        }
        searchCriteria.add(groupCriterion);

        return searchCriteria;
    }
}
